//============================================================================
// Copyright (C) 2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include "VxUtilLib.h"
#include "VxSemaphore.h"
#include <time.h> 

//============================================================================--
//=== constructor ===//
VxSemaphore::VxSemaphore()
{
#ifdef WIN_PLATFORM
	m_hAccessLock = CreateSemaphore( NULL, 0, 5000, NULL );
#else
	sem_init( &m_oSemaphore, 0, 0 );
#endif
}
//============================================================================--
//=== destructor ===//
VxSemaphore::~VxSemaphore()
{
#ifdef WIN_PLATFORM
	if( m_hAccessLock )
	{
		CloseHandle( m_hAccessLock );
		m_hAccessLock = NULL;
	}
#endif
}

//============================================================================--
//! wait until another thread calls Signal
bool VxSemaphore::Wait( int iTimeoutMilliseconds )
{
#ifdef WIN_PLATFORM
	DWORD result;
	if( 0 == iTimeoutMilliseconds )
	{
		result = WaitForSingleObject(	m_hAccessLock,
										INFINITE );
	}
	else
	{
		result = WaitForSingleObject(	m_hAccessLock,
										iTimeoutMilliseconds );
	}
	if( WAIT_OBJECT_0 == result )
	{
		return true;
	}
	return false;
#else
	if( 0 == iTimeoutMilliseconds )
	{
		return (0 == sem_wait( &m_oSemaphore ) );
	}
	else
	{
		struct timespec ts;
		if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
			log_msg( LOG_FATAL, "VxSemaphore::Wait: failed getting real time clock\n" );
		ts.tv_sec += iTimeoutMilliseconds/1000;
		ts.tv_nsec += (iTimeoutMilliseconds%1000) * 1000;

		return (0 == sem_timedwait( &m_oSemaphore, &ts ) );
	}
#endif
}
//============================================================================--
//! signal waiting thread to run
int VxSemaphore::Signal( void )
{
#ifdef WIN_PLATFORM
	if (!ReleaseSemaphore(
			m_hAccessLock,  // handle to semaphore
			1,           // increase count by one
			NULL) )      // not interested in previous count
	{
		return -1;
	}
	else
		return 0;
#else
	return sem_post( &m_oSemaphore );
#endif
}

